#include <iostream>
#include <cstdlib>
#include <fstream>
#include <sqlite3.h>
#include <vector>
#include <sstream>
#include <cctype>
#include <string>
#include <cstring>

using namespace std;

class Database{
	public:
		Database(char* filename);
		~Database();

		sqlite3* getSqlite3();
		int getFail();

		void open(char* filename);

		void close();

		vector<vector<string> > query(string );


	private:
		sqlite3 *db;
		int fail;
};

Database::Database(char *filename){
  db=NULL;
  open(filename);
  fail=0;
}

Database::~Database(){

}

sqlite3* Database::getSqlite3(){
	return db;
}

void Database::open(char * filename){
  int rc = sqlite3_open(filename, &db);
  
  if(rc){
    cout << "Can't open database\n";
    fail = 1;
  } 
  else {
    cout << "Open database successfully\n";
  } 

}

int Database::getFail(){
	return fail;
}

vector<vector<string> > Database::query(string statement){
/**
*  Short story : throw your sql statement into this function and it will return results
*  
*	read the following to understand
*/

  sqlite3_stmt* res; // this is sqlite's results output pointer
  const char* tail; // i have no idea what this does actually.
  
  // one row contains many outputs (e.g id, firstname, lastname)  therefore vector<string> 
  // there might be more than 1 row everytime you execute therefore you need a listOfRows
  vector<vector<string> > listOfRows;

  // the actual execution of the statement. returns a number for validation
 int error = sqlite3_prepare_v2(db, statement.c_str(), statement.length(), &res, &tail);  
 
  if (error != SQLITE_OK){ // if unable to execute statements
    cout << "Unable to prepare statement!" <<endl;
    sqlite3_close(db);
  }
  else{ // if execution okay

    int cols = sqlite3_column_count(res); // count the number of columns that the statement will output

	while (sqlite3_step(res) == SQLITE_ROW){ // for every row of results
		// for every row of results, redeclare resultsInOneRow. (to wipe clean).
		vector<string> resultsInOneRow; 
		
		for (int i=0;i<cols;i++){ // start of reading the output
								  // using cols to tell the program how many columns in one row
			
			// cout << sqlite3_column_text(res,i) <<endl; // display results in one column
			
			// results is in const unsigned char*. re-cast it to string
			string temp = string(reinterpret_cast<const char*>(sqlite3_column_text(res,i))); 
			
			// push that string into a vector.
			resultsInOneRow.push_back(temp);
		
		}// end of reading the results in one row

		// push the row into a list of rows.
		listOfRows.push_back(resultsInOneRow);

    
	 }// end of reading every row
	 
	 sqlite3_finalize(res); // clear statement.
  }// end else prepare statement is ok

  // return the listOfRows
  return listOfRows;

}


void Database::close(){
        sqlite3_close(db);   
}
